#include "RpcClient.h"
#include "MyRpc.h"
#include "MessageHeader.pb.h"
#include "ZkClient.h"
#include "TcpConnectionPool.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string>


// 构造buffer
/*
buffer = header_size（4Byte） + header_str + args_str
header_str = service_name + method_name + args_size
*/
void RpcClient::CallMethod(const google::protobuf::MethodDescriptor *method,
                            google::protobuf::RpcController *controller,
                            const google::protobuf::Message *request,
                            google::protobuf::Message *response,
                            google::protobuf::Closure *done)
{
    // 获取service_desc
    const google::protobuf::ServiceDescriptor *service_desc = method->service();
    // 获取service_name
    std::string service_name = service_desc->name();
    // 获取method_name
    std::string method_name = method->name();

    // 获取args_str和args_size
    std::string args_str = "";
    uint32_t args_size = 0;
    if(request->SerializeToString(&args_str))
    {
        args_size = args_str.size();
    }
    else 
    {
        // std::cout << "request->SerializeToString() error" << std::endl;
        LOG_ERROR("request->SerializeToString() error");
        return;
    }

    // 构造header_str，获取header_size
    MessageHeader::MessageHeader message_header;
    message_header.set_service_name(service_name);
    message_header.set_method_name(method_name);
    message_header.set_args_size(args_size);

    uint32_t header_size = 0;
    std::string header_str = "";
    if(message_header.SerializeToString(&header_str))
    {
        header_size = header_str.size();
    }
    else 
    {
        // std::cout << "message_header.SerializeToString() error" << std::endl;
        LOG_ERROR("message_header.SerializeToString() error");
        return;
    }

    // 构造buffer
    std::string send_buf;
    send_buf.append((char *)&header_size, 4);
    send_buf.append(header_str);
    send_buf.append(args_str);

    // 打印信息
    // std::cout << "*******************************" << std::endl;
    // std::cout << "service_name:" << service_name << " method_name:" << method_name << " args_size:" << args_size << std::endl;  
    // std::cout << "header_size:" << header_size << " header_str:" << header_str << std::endl;
    // std::cout << "send_buf:" << send_buf << std::endl;
    // std::cout << "*******************************" << std::endl;
    LOG_INFO("*******************************");
    LOG_INFO("service_name:%s method_name:%s args_size:%d", service_name.c_str(), method_name.c_str(), args_size);
    LOG_INFO("header_size:%d header_str:%s", header_size, header_str.c_str());
    LOG_INFO("send_buf:%s", send_buf.c_str());
    LOG_INFO("*******************************");

    // 发送数据
    // 初始化socket
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if(fd == -1)
    {
        // std::cout << "socket() error" << std::endl;
        LOG_ERROR("socket() error");
        return;
    }

    // // 从zk获取ip和port
    // std::string zk_ip = MyRpc::GetInstance().GetConfig().GetConfig("zookeeper_ip");
    // uint16_t zk_port = std::stoi(MyRpc::GetInstance().GetConfig().GetConfig("zookeeper_port"));
    // ZkClient zk_client;
    // zk_client.Connect(zk_ip, zk_port);
    // std::string host = zk_client.GetData("/" + service_name + "/" + method_name);
    // if(host.empty())
    // {
    //     LOG_ERROR("zk_client.GetData() error");
    //     close(fd);
    //     return;
    // }
    // // 依据":"切割host，获得ip和port
    // std::string ip = host.substr(0, host.find(":"));
    // uint16_t port = std::stoi(host.substr(host.find(":") + 1));
    
    
    // 配置地址
    std::string ip = MyRpc::GetInstance().GetConfig().GetConfig("rpc_server_ip");
    uint16_t port = std::stoi(MyRpc::GetInstance().GetConfig().GetConfig("rpc_server_port"));
    // struct sockaddr_in server_addr;
    // server_addr.sin_family = AF_INET;
    // server_addr.sin_port = htons(port);
    // server_addr.sin_addr.s_addr = inet_addr(ip.c_str());

    // // 连接服务器
    // if(-1 == connect(fd, (struct sockaddr *)&server_addr, sizeof(server_addr)))
    // {
    //     // std::cout << "connect() error" << std::endl;
    //     LOG_ERROR("connect() error");
    //     close(fd); 
    //     return;
    // }

    // 从连接池获取连接
    std::shared_ptr<TCPConnection> conn = m_tcp_conn_pool->getConnectionFromPool(ip, port);

    // 发送数据
    if(-1 == send(conn->sockfd, send_buf.c_str(), send_buf.size(), 0))
    {
        // std::cout << "send() error" << std::endl;
        LOG_ERROR("send() error");
        m_tcp_conn_pool->releaseConnection(conn);
        return;
    }

    // 接收回复
    char recv_buf[1024] = {0};
    int recv_len = 0;
    if (-1 == (recv_len = recv(conn->sockfd, recv_buf, 1024, 0)))
    {
        // std::cout << "recv() error" << std::endl;
        LOG_ERROR("recv() error");
        m_tcp_conn_pool->releaseConnection(conn);
        return;
    }

    // 反序列化接收到的数据
    if(!response->ParseFromArray(recv_buf, recv_len))
    {
        // std::cout << "response->ParseFromArray() error" << std::endl;
        LOG_ERROR("response->ParseFromArray() error");
        m_tcp_conn_pool->releaseConnection(conn);
        return;
    }

    m_tcp_conn_pool->releaseConnection(conn);
}